/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2023. All rights reserved.
 */

package util

// Copyright 2019 Huawei Technologies Co.,Ltd.
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
// this file except in compliance with the License.  You may obtain a copy of the
// License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations under the License.

import (
	"bytes"
	"io"
	"prim-server/config"
	"prim-server/logger"

	"github.com/huaweicloud/huaweicloud-sdk-go-obs/obs"
)

// 头像等普通图片桶
var (
	obsEndpoint = config.GetConfig().OBSConfig.Endpoint
	obsAK       = config.GetConfig().OBSConfig.AK
	obsSK       = config.GetConfig().OBSConfig.SK
	bucketName  = config.GetConfig().OBSConfig.BucketName
)

// 实名认证图片桶
var (
	cocObsEndpoint = config.GetConfig().COCOBSConfig.Endpoint
	cocObsAK       = config.GetConfig().COCOBSConfig.AK
	cocObsSK       = config.GetConfig().COCOBSConfig.SK
	cocBucketName  = config.GetConfig().COCOBSConfig.BucketName

	cocIDCardFileDir = "download"
)

var obsClient *obs.ObsClient
var cocObsClient *obs.ObsClient

const (
	urlValidityPeriod = 3600 * 2
)

func getObsClient() *obs.ObsClient {
	var err error
	if obsClient == nil {
		obsClient, err = obs.New(obsAK, obsSK, obsEndpoint)
		if err != nil {
			logger.Error("getObsClient :%v", err)
		}
	}
	return obsClient
}
func getCOCObsClient() *obs.ObsClient {
	var err error
	if cocObsClient == nil {
		cocObsClient, err = obs.New(cocObsAK, cocObsSK, cocObsEndpoint)
		if err != nil {
			logger.Error("getObsClient :%v", err)
		}
	}
	return cocObsClient
}

// 在OBS中创建文件夹
func CreateFolder(obsClient *obs.ObsClient, filePath string) error {
	if filePath[len(filePath)-1] != '/' {
		filePath = CombineTwoString(filePath, "/")
	}
	input := &obs.PutObjectInput{}
	input.Bucket = bucketName
	input.Key = filePath
	output, err := obsClient.PutObject(input)
	if err == nil {
		logger.Info("RequestId:%s", output.RequestId)
	} else if obsError, ok := err.(obs.ObsError); ok {
		logger.Error("Code:%s Message:%s", obsError.Code, obsError.Message)
	}
	return err
}

// 上传身份证文件和头像到指定桶中
func UploadIDCardFile(obsKey string, data []byte) (string, error) {
	reader := bytes.NewReader(data)
	cocObsClient := getCOCObsClient()
	bucket := cocBucketName
	finalKey := cocIDCardFileDir + "/" + obsKey
	return UploadData(bucket, finalKey, reader, cocObsClient)
}

// 上传头像到指定桶中
func UploadProfilePhotoFile(obsKey string, data []byte) (string, error) {
	reader := bytes.NewReader(data)
	obsClient := getObsClient()
	bucket := bucketName
	return UploadData(bucket, obsKey, reader, obsClient)
}

// 给定图片在obs上的路径，返回带授权的url，默认有效时间为1个小时
// OBSkey和Asset表中的SaveUrl等价
func GetFileUrl(obsKey string) (string, error) {
	if len(obsKey) == 0 {
		return "", nil
	}
	getObjectInput := &obs.CreateSignedUrlInput{}
	getObjectInput.Method = obs.HttpMethodGet
	getObjectInput.Bucket = bucketName
	getObjectInput.Key = obsKey
	getObjectInput.Expires = urlValidityPeriod //1 hour
	getObjectOutput, err := getObsClient().CreateSignedUrl(getObjectInput)
	if err != nil {
		return "", err
	}
	return getObjectOutput.SignedUrl, nil
}

// 上传文件--返回OBS上的URL--流式上传
func UploadData(bucketName, obsKey string, fileReader io.Reader, obsClient *obs.ObsClient) (string, error) {
	finalKey := obsKey
	input := &obs.PutObjectInput{}
	input.Bucket = bucketName
	input.Key = finalKey
	input.Body = fileReader
	output, err := obsClient.PutObject(input)
	if err == nil {
		//选择查看上传成功参数
		logger.Info("Request ID:%s\n", output.RequestId)
	} else if obsError, ok := err.(obs.ObsError); ok {
		logger.Error("Code:%s\n", obsError.Code)
		logger.Error("Message:%s\n", obsError.Message)
	}
	return finalKey, err
}

// 下载文件--返回data
func DownloadFile(obsKey string) ([]byte, error) {
	input := &obs.GetObjectInput{}
	input.Bucket = bucketName
	input.Key = obsKey
	output, err := getObsClient().GetObject(input)
	var data []byte
	if err == nil {
		defer output.Body.Close()
		p := make([]byte, 1024)
		var readErr error
		var readCount int
		// 读取对象内容
		for {
			readCount, readErr = output.Body.Read(p)
			if readCount > 0 {
				data = append(data, p...)
			}
			if readErr != nil {
				break
			}
		}
	} else if obsError, ok := err.(obs.ObsError); ok {
		logger.Error("Code:%s\n", obsError.Code)
		logger.Error("Message:%s\n", obsError.Message)
	}
	return data, nil
}

// 上传身份证到桶时的前缀
func BuildPrefixForIDCard(userId string) string {
	return cocIDCardFileDir + "/" + userId
}

// 列举桶内对象的Key
func ListBuckObjectForIDCard(userId, prefix string) ([]string, error) {
	cocObsClient := getCOCObsClient()
	bucket := cocBucketName
	input := &obs.ListObjectsInput{
		Bucket: bucket,
		ListObjsInput: obs.ListObjsInput{
			Prefix: prefix,
		},
	}
	output, err := cocObsClient.ListObjects(input)
	var listOfObject []string
	if err == nil {
		logger.Info("RequestId:%s\n", output.RequestId)
		for _, val := range output.Contents {
			listOfObject = append(listOfObject, val.Key)
		}
	} else if obsError, ok := err.(obs.ObsError); ok {
		logger.Error("Code:%s\n", obsError.Code)
		logger.Error("Message:%s\n", obsError.Message)
	}
	return listOfObject, err
}
